/* 
 * 时间：2020年11月4日16点33分
 * 作者：ZQD
 * 功能：   
 *      求出多项式在x处的大小
 *      即求f(x) = a0 + a1 * x + a2 * x^2 + a3 * x^3 + ... + an * x^n在x处的值
 *      在本函数中，令f(x) = 0 + x + 2 * x^2 + ... + 9 * x^9，即a[i] = i
 * 
 * 在本函数中学习到的东西：
 *      1. 利用time.h库中的函数，计算某一段代码执行的时间，如果时间过于短暂，可以多次执行相关代码取平均值
 *      2. 利用秦九韶算法求解多项式在某处的值
 *      3. 机器运算加减法的速度比运算乘除法的速度要快很多
 */

#include <stdio.h>
// 需要计时，引用time.h库
#include <time.h>
// 需要用到pow函数，引用math.h库
#include <math.h>

// 定义多项式的项数
#define MAXN 10

// 定义函数执行的次数，因为执行一次函数所需的时间过短，所以需要多次使用
#define TIMES 1000000

// 定义两个变量，用来记录开始时间和结束时间
// clock_t 是clock()函数返回的变量类型
// clock()函数的时间单位是clock_tick，即“时钟打点”
clock_t start, stop;

// 定义一个变量，用来计算所用的时间，单位是秒
double duration;

double f_bad(int, double a[], double);
double f_better(int, double a[], double);

int main(void)
{
    int i;
    // 定义多项式的常数项
    double a[MAXN];
    // 定义求解位置
    double x = 1.1;

    // 从这里开始是为了给多项式的各项系数赋值，不同多项式不同，酌情修改
    for (i = 0; i < MAXN; ++i)
        a[i] = (double)i;
    // 给多项式的各项系数赋值结束

    start = clock();
    for (i = 0; i < TIMES; ++i)
        f_bad(MAXN - 1, a, x);
    stop = clock();
    // CLK_TCK是机器时钟每秒所走的时钟打点数，也可用CLOCKS_PER_SEC

    duration = ((double)(stop - start)) / CLK_TCK / TIMES;
    printf("ticks1 = %f\n", (double)(stop - start));
    printf("time1 = %6.2es\n", duration);

    start = clock();
    for (i = 0; i < TIMES; ++i)
        f_better(MAXN - 1, a, x);
    stop = clock();
    duration = ((double)(stop - start)) / CLK_TCK / TIMES;
    printf("ticks2 = %f\n", (double)(stop - start));
    printf("time2 = %6.2es\n", duration);

    return 0;
}

double f_bad(int n, double a[], double x)
{
    /* 
     * 本函数的功能：利用效率较差的方式实现n阶多项式在x处的值
     * n   --------> 多项式的阶数
     * a[] --------> 多项式各项的系数
     * x   --------> 所求位置
     */

    int i;
    double sum = a[0];
    for (i = 1; i <= n; ++i)
    {
        sum += a[i] * pow(x, i);
    }
    return sum;
}

double f_better(int n, double a[], double x)
{
    /* 
     * 本函数的功能：利用效率较高的方式实现n阶多项式在x处的值
     * 思路来自秦九韶的多项式求解公式
     * n   --------> 多项式的阶数
     * a[] --------> 多项式各项的系数
     * x   --------> 所求位置
     */

    int i;
    double sum = a[n];
    for (i = n; i > 0; --i)
    {
        sum = a[i - 1] + x * sum;
    }
    return sum;
}